package com.pad.dpscn.daag.sdk.core.autoconfigure;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.Order;

import com.pad.dpscn.daag.sdk.common.utils.SpringUtils;
import com.pad.dpscn.daag.sdk.core.aspect.DataCaptureAspect;
import com.pad.dpscn.daag.sdk.core.async.AsyncQueryDbAndSendMsgService;
import com.pad.dpscn.daag.sdk.core.async.AsyncQueryDbAndSendMsgServiceImpl;
import com.pad.dpscn.daag.sdk.core.condition.DaagEffectCondition;
import com.pad.dpscn.daag.sdk.core.interceptor.MybatisMapperInterceptor;
import com.pad.dpscn.daag.sdk.core.properties.DaagProperties;
import com.pad.dpscn.daag.sdk.core.strategy.MessageQueueStrategy;
import com.pad.dpscn.daag.sdk.core.strategy.rocketmq.RocketMQMessageQueueStrategy;
import com.pad.dpscn.daag.sdk.core.strategy.service.MessageQueueService;

/**
 * 
 * com.pad.dpscn.daag.sdk.core.autoconfigure Description:
 * 
 * @Configuration: 标记这个类是一个Spring配置类，Spring会处理这个类中的@Bean方法，用于生成bean定义并注册到Spring应用上下文中。 @Conditional(DaggEffectCondition.class):
 *                 表示这个配置类只在满足DaggEffectCondition条件时才会被加载。DaggEffectCondition可能是一个自定义的条件类，用于检查某些特定的条件是否满足。
 * @ConditionalOnClass: 表示只有当指定的类存在于类路径下时，才会加载这个配置类。这里指定了MybatisAutoConfiguration.class,
 *                      RocketMQAutoConfiguration.class, 和
 *                      Interceptor.class，确保这些类在类路径下可用。
 * @ConditionalOnMissingBean: 这个注解在这段代码中并没有直接使用，但通常在自动配置类中用来确保只有当某个bean不存在时，才会创建另一个bean。
 * @ConditionalOnProperty: 这个注解通常用于根据application.properties或application.yml文件中的属性值来决定是否加载某个配置。
 * @EnableConfigurationProperties: 用于启用对@ConfigurationProperties注解的支持，允许将外部属性绑定到bean上。
 * @EnableAspectJAutoProxy: 启用Spring AOP支持，使@Aspect注解的类生效。
 * @author yangdezhao
 * @since 2024年3月11日
 * @version 1.0
 */
@Configuration
@EnableConfigurationProperties({ DaagProperties.class })
@Conditional(DaagEffectCondition.class)
@Import(RocketMQConfig.class)
@AutoConfigureAfter({ MybatisAutoConfiguration.class, RocketMQAutoConfiguration.class })
@ConditionalOnClass({ RocketMQConfig.class, MybatisAutoConfiguration.class, Interceptor.class }) // 确保SqlSessionFactory和Interceptor在类路径中
@ConditionalOnProperty(prefix = DaagProperties.DAGG_DATA_INTERCEPTOR_PROFIEX, name = "enable", havingValue = "true")
@EnableAspectJAutoProxy(proxyTargetClass = true)
@AutoConfigureOrder(2)
public class DaoInterceptorAutoConfiguration {

	public static final String MESSAGE_QUEUE_SERVICE_NAME = "messageQueueService";

	public static final String SPRING_UTILS_NAME = "springUtils";

	public static final String MYBATIS_MAPPER_INTERCEPTOR_NAME = "mybatisMapperInterceptor";

	public static final String MESSAGE_QUEUE_STRATEGY_NAME = "messageQueueStrategy";

	public static final String DATA_DAAG_ASPECT_NAME = "dataCaptureAspect";

	public static final String ASYNC_QUERYDB_AND_SENDMSG_SERVICE_NAME = "asyncQueryDbAndSendMsgService";

	public static final String MESSSAGE_QUENE_SINGLETON_NAME = "messsageQueneSingleton";

	public static final String DAGG_DEFAULT_TOPIC_NAME = "dagg-default-topic";


	@Bean("daagProperties")
	@Order(1)
	@ConditionalOnMissingBean(DaagProperties.class)
	public DaagProperties daagProperties() {
		return new DaagProperties();
	}
	@Bean("rocketMQTemplate")
	@ConditionalOnMissingBean(RocketMQTemplate.class)
	@Order(1)
	public RocketMQTemplate rocketMQTemplate() {
		return new RocketMQTemplate();
	}

	@Bean(SPRING_UTILS_NAME)
	@ConditionalOnMissingBean(SpringUtils.class)
	public SpringUtils springUtils() {
		return new SpringUtils();
	}

	/**
	 * mybatis 拦截器注册
	 */

	@Bean(MYBATIS_MAPPER_INTERCEPTOR_NAME)
	@ConditionalOnMissingBean(MybatisMapperInterceptor.class)
	public Interceptor mybatisMapperInterceptor(DaagProperties daagProperties) { // 创建并返回自定义的拦截器实例
		return new MybatisMapperInterceptor(daagProperties);
	}

	@Bean(MESSAGE_QUEUE_SERVICE_NAME)
	@ConditionalOnMissingBean(MessageQueueService.class)
	@DependsOn("rocketMQTemplate") 
	public MessageQueueService messageQueueService(RocketMQTemplate rocketMQTemplate,DaagProperties daagProperties) {
		String topicName = (daagProperties.getTopicName() == null
				|| StringUtils.isEmpty(daagProperties.getTopicName().trim())) ? DAGG_DEFAULT_TOPIC_NAME
						: daagProperties.getTopicName();
		MessageQueueService messageQueueService = new MessageQueueService(topicName);
		messageQueueService.registerStrategy("rocketmq", new RocketMQMessageQueueStrategy(rocketMQTemplate));
		return messageQueueService;
	}

	@Bean(MESSAGE_QUEUE_STRATEGY_NAME)
	@ConditionalOnMissingBean(MessageQueueStrategy.class)
	@DependsOn("rocketMQTemplate")
	public MessageQueueStrategy messageQueueStrategy(RocketMQTemplate rocketMQTemplate) {
		return new RocketMQMessageQueueStrategy(rocketMQTemplate);
	}

	@Bean(DATA_DAAG_ASPECT_NAME)
	@ConditionalOnMissingBean(DataCaptureAspect.class)
	public DataCaptureAspect datadaagAspect() {
		return new DataCaptureAspect();
	}

	@Bean(ASYNC_QUERYDB_AND_SENDMSG_SERVICE_NAME)
	@ConditionalOnMissingBean(AsyncQueryDbAndSendMsgServiceImpl.class)
	public AsyncQueryDbAndSendMsgService asyncQueryDbAndSendMsgService() {
		return new AsyncQueryDbAndSendMsgServiceImpl();
	}

}
